home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / viewers / polyview / polyvw31.lha / Polyview3.1 / new / pvpick.c < prev    next >
C/C++ Source or Header  |  1993-07-13  |  22KB  |  776 lines

  1. /*****************************************************************************
  2.  * NCSA Polyview 3.0                                                         *
  3.  *                                                                           *
  4.  * Version 3 changes and additions by Marc Andreessen.                       *
  5.  * Version 2 by Brian Calvert.                                               *
  6.  *                                                                           *
  7.  * Software Development Group                                                *
  8.  * National Center for Supercomputing Applications                           *
  9.  * University of Illinois at Urbana-Champaign                                *
  10.  *                                                                           *
  11.  * This is BETA release software.  As such it may contain software bugs and  *
  12.  * exhibit inconsistencies.                                                  *
  13.  *                                                                           *
  14.  * Please send bug reports to polyview@ncsa.uiuc.edu.                        *
  15.  *                                                                           *
  16.  * Copyright (c) 1992 The Board of Trustees of the University of Illinois.   *
  17.  *                                                                           *
  18.  * Permission to use, copy, and modify this software and its                 *
  19.  * documentation for educational, research, and non-profit purposes is       *
  20.  * hereby granted, provided that the above copyright notice, the original    *
  21.  * authors names, and this permission notice appear in all such copies.      *
  22.  * Any distribution of this software requires the explicit and written       *
  23.  * authorization of the authors.                                             *
  24.  *                                                                           *
  25.  * The University of Illinois makes no representations about the             *
  26.  * suitability of this software for any purpose.  It is provided "as is"     *
  27.  * without warranty of any kind.                                             *
  28.  *****************************************************************************/
  29.  
  30. /* $Header: /usr3/people/gbourhis/pv3/new/RCS/pvpick.c,v 1.2 93/07/13 16:45:06 gbourhis Exp $ */
  31.  
  32. #ifdef RCSLOG
  33. $Log:    pvpick.c,v $
  34.  * Revision 1.2  93/07/13  16:45:06  gbourhis
  35.  * fix a bug in PickVertices(): loadname() must not be called between
  36.  * bgnpoint() & endpoint().
  37.  * 
  38.  * Revision 1.1  92/09/18  10:55:26  marca
  39.  * Initial revision
  40.  * 
  41. #endif
  42.  
  43. #include "pv.h"
  44.  
  45. #define PI 3.14159265
  46.  
  47.  
  48. /* ------------------------------ PickRegion ------------------------------ */
  49. int PickRegion (state_t *state, window_t *win, short left, short bottom,
  50.                 short right, short top, int toggle, int interactive)
  51. {
  52.   polyview_t *pv = (polyview_t *)WIN_IMAGE(win);
  53.   char line[MAXLINELEN];
  54.  
  55.   XmxWinset (pv->drawing_volume);
  56.  
  57.   /* If the pick window has zero area in either dimension, grow it */
  58.   /* equally in both directions. */
  59.   if (left == right) 
  60.     {
  61.       left--;
  62.       right++;
  63.     }
  64.   if (bottom == top) 
  65.     {
  66.       bottom--;
  67.       top++;
  68.     }
  69.   
  70.   /* Echo the picking region to the transcript file. */
  71.   if (state->transcript_fp != NULL)
  72.     fprintf(state->transcript_fp, "select area %d %d %d %d %s\n",
  73.             (int) left, (int) bottom, (int) right, (int) top, 
  74.             (toggle) ? "toggle" : "notoggle");
  75.  
  76.   if (!interactive)
  77.     {
  78.       sprintf (line, "select area %d %d %d %d %s\0",
  79.                (int) left, (int) bottom, (int) right, (int) top, 
  80.                (toggle) ? "toggle" : "notoggle");
  81.       GUIaddCommand (line);
  82.     }
  83.  
  84.   /* Recursively select from the objects. */
  85.   PickPolyview(state, win, win->pickmode, left, right, bottom, top,
  86.                toggle);
  87.   
  88.   /* Send the message that something new was picked.
  89.      This effects a set_redraw call. */
  90.   broadcast_msg(state, win, MSG_NEWPICK);
  91.   
  92.   return ST_OKAY;
  93. }
  94.  
  95.  
  96.  
  97. /* ---------------------------- PickNoObjects ----------------------------- */
  98. static long PickNoObjects (state_t *state, object_t *object, va_list args)
  99. {
  100.   OBJ_PICKMODE(object) = PICK_NONE;
  101.   OBJ_HITS(object) = 0;
  102.   return 1;
  103. }
  104.  
  105.  
  106. /* -------------------------------- PickNo -------------------------------- */
  107. void PickNo (state_t *state, window_t *win)
  108. {
  109.   /* Unselect all of the objects in the tree. */
  110.   if (WinHasData(win) && (WIN_ROOTOBJ(win) != NULL))
  111.     ApplyFuncToTree(state, WIN_ROOTOBJ(win), PickNoObjects);
  112.   return;
  113. }
  114.  
  115.  
  116. /* ---------------------------- PickAllObjects ---------------------------- */
  117. static long PickAllObjects (state_t *state, object_t *object, va_list args)
  118. {
  119.   OBJ_PICKMODE(object) = PICK_ALL;
  120.   OBJ_HITS(object) = 1;
  121.   return 1;
  122. }
  123.  
  124.  
  125. /* ------------------------------- PickAll -------------------------------- */
  126. void PickAll (state_t *state, window_t *win)
  127. {
  128.   /* Select all of the objects in the tree. */
  129.   if (WinHasData(win) && (WIN_ROOTOBJ(win) != NULL))
  130.     ApplyFuncToTree(state, WIN_ROOTOBJ(win), PickAllObjects);
  131.   return;
  132. }
  133.  
  134.  
  135. /* ----------------------------- PickPolyview ----------------------------- */
  136. int PickPolyview (state_t *state, window_t *win, pickmode_t mode,
  137.                   long left, long right, long bottom, long top, int toggle)
  138. {
  139.   polyview_t *polyview;
  140.   object_t *obj;
  141.   float    maxwidth;
  142.   
  143.   static Matrix    ident = 
  144.     {
  145.       {1.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0}, 
  146.       {0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 1.0}
  147.     }, s;
  148.   
  149.   int i, j;
  150.   
  151.   float    xaspect, yaspect;
  152.   float    width, height;
  153.   float    bx, by;
  154.   float    dx, dy;
  155.   float    tx, ty;
  156.   Matrix op;
  157.   
  158.   long first_id;
  159.   
  160.   /* Get a pointer to the root object associated with the window. */
  161.   polyview = (polyview_t *) win->image;
  162.   assert (polyview != NULL);
  163.   
  164.   if (WIN_FRAME(win) == NULL) 
  165.     {
  166.       /* Make sure there's really nothing to draw. */
  167.       assert (WIN_FRAMELIST(win) == NULL);
  168.       /* There's nothing to draw. */
  169.       return ST_OKAY;
  170.     }
  171.   else 
  172.     {
  173.       obj = FRA_ROOTOBJ(WIN_FRAME(win));
  174.     }
  175.     
  176.   /* Make sure that the object exists, has information associated */
  177.   /* with it, and has a drawing function. */
  178.   assert (obj != NULL);
  179.   assert (obj->info != NULL);
  180.   assert (obj->info->draw_fn != NULL);
  181.   
  182.   /* Save the transformation matrix and the drawing attributes. */
  183.   mmode (MPROJECTION);
  184.   getmatrix (s);
  185.   mmode (MVIEWING);
  186.  
  187.   /* When MSINGLE mode is entered, matrix and stack are cleared out
  188.      anyway, so no reason to save them. */
  189.   /* pushmatrix(); */
  190.   pushviewport();
  191.   pushattributes();
  192.  
  193.   mmode (MSINGLE);
  194.   
  195.   /* Set up the window's drawing conditions:  projection matrix, */
  196.   /* zbuffering, shading, and so on. */
  197.   maxwidth = WIN_MAXWIDTH(win);
  198.   height = (float) WIN_HEIGHT(win);
  199.   width = (float) WIN_WIDTH(win);
  200.   
  201.   if (WIN_PROJECTION(win) == ORTHOGRAPHIC)
  202.     {
  203.       /* Use the spherical viewing distance to determine the scale */
  204.       /* to magnify by. */
  205.       float scl;
  206.       
  207.       /* Calculate the aspect ratio acaling multiplier.  This is */
  208.       /* applied to the x-dimension to adjust for the change in */
  209.       /* aspect ratio of a resizable window. */
  210.       if (width > height) 
  211.         {
  212.           xaspect = height / width;
  213.           yaspect = 1.0;
  214.         }
  215.       else 
  216.         {
  217.           xaspect = 1.0;
  218.           yaspect = width / height;
  219.         }
  220.       
  221.       /* Initialize the transformation matrix */
  222.       mmode (MPROJECTION);
  223.       loadmatrix(ident);
  224.       
  225.       /* Build an orthographic projection matrix and load it. */
  226.       for (i = 0; i < 4; i++)
  227.         for (j = 0; j < 4; j++)
  228.           op[i][j] = 0.0;
  229.       
  230.       op[0][0] = (2 / maxwidth) * xaspect;
  231.       op[1][1] = 2 / maxwidth * yaspect;
  232.       op[2][2] = -2 / maxwidth;
  233.       op[3][3] = 1.0;
  234.       multmatrix(op);
  235.       
  236.       mmode (MVIEWING);
  237.       loadmatrix (ident);
  238.       
  239.       scl = maxwidth/(WIN_SFROM(win)[RHO]);
  240.       scale(scl, scl, 1.0);
  241.     }
  242.   else 
  243.     {
  244.       float dist;
  245.       
  246.       dist = fhypot(WIN_CFROM(win)[X]-WIN_STATS(win,PX).mean,
  247.                     fhypot(WIN_CFROM(win)[Y]-
  248.                            WIN_STATS(win,PY).mean,
  249.                            WIN_CFROM(win)[Z]-
  250.                            WIN_STATS(win,PZ).mean));
  251.       
  252.       perspective(WIN_FOV(win),
  253.                   (float) (WIN_WIDTH(win))/WIN_HEIGHT(win),
  254.                   MAX(0.01, dist-1.1*maxwidth), dist+1.1*maxwidth);
  255.       
  256.       translate(0.0, 0.0, -WIN_SFROM(win)[RHO]);
  257.     }
  258.   
  259.   /* Insert the region-drawing transformation before the current viewing */
  260.   /* transformation. */
  261.   getmatrix(op);
  262.   loadmatrix(ident);
  263.   
  264.   bx = left;
  265.   by = bottom;
  266.   dx = right - left;
  267.   dy = top - bottom;
  268.   
  269.   scale(width/dx, height/dy, 1.0);
  270.   tx = -2.0 * (((bx + dx/2.0) - width/2.0)/width);
  271.   ty = -2.0 * (((by + dy/2.0) - height/2.0)/height);
  272.   translate(tx, ty, 0.0);
  273.   
  274.   multmatrix(op);
  275.  
  276.   /* This rotate should match the rotate in pvpoly.c */
  277.   rotate (WIN_TWIST(win), 'z');
  278.     
  279.   rot(90.0-WIN_SFROM(win)[PHI]*180.0/PI,'x');
  280.   rot(-90.0-WIN_SFROM(win)[THETA]*180.0/PI,'y');
  281.   rot(-90.0, 'x');
  282.   
  283.   translate(-WIN_AT(win)[X],-WIN_AT(win)[Y],-WIN_AT(win)[Z]);
  284.   
  285.   zbuffer(FALSE);
  286.   
  287.   /* Get the image root object and recursively pick the object */
  288.   /* structure.  If nothing is selected, that effectively means that */
  289.   /* all objects are selected. */
  290.   first_id = 1;
  291.   if (PickObjRecurs(state, win, obj, obj->info, mode, toggle, &first_id) == 0)
  292.     PickAll(state, win);
  293.   
  294.   /* Restore the transformation matrix and z-buffer. */
  295.   mmode (MPROJECTION);
  296.   loadmatrix (s);
  297.   mmode (MVIEWING);
  298.  
  299.   popattributes();
  300.   popviewport();
  301.   /* When MSINGLE is entered/left, matrix stack is emptied. */
  302.   /* popmatrix(); */
  303.  
  304.   zbuffer(TRUE);
  305.   
  306.   return ST_OKAY;
  307. }
  308.  
  309.  
  310. /* ---------------------------- PickObjRecurs ----------------------------- */
  311. int PickObjRecurs (state_t *state, window_t *win, object_t *obj,
  312.                    objinfo_t *info, pickmode_t mode, int toggle, 
  313.                    long *first_id)
  314. {
  315.   objinfo_t local_info;
  316.   object_t *child;
  317.   long hits;
  318.   
  319.   /* If we don't need to pick this object tree, then return. */
  320.   if (obj->type & INACTIVE)
  321.     return 0;
  322.   
  323.   /* Save the current transformation matrix context, since update_info */
  324.   /* may change it and the recursive drawing steps will want to use */
  325.   /* it. */
  326.   pushmatrix();
  327.   pushattributes();
  328.   
  329.   /* Process the new attributes and transformations to develop a new */
  330.   /* local info block.  Update only those fields that have new values. */
  331.   update_info(state, info, obj->info, &local_info);
  332.     
  333.   /* Set the id of the object's first selected element, if any. */
  334.   OBJ_FIRSTID(obj) = *first_id;
  335.   
  336.   /* Using this information, either draw the object or decompose it */
  337.   /* further. */
  338.   if (obj->type & ATOM) 
  339.     {
  340.       /* Go ahead and draw objects using the currently active draw */
  341.       /* function */
  342.       switch (mode) 
  343.         {
  344.         case PICK_VERTEX:
  345.           hits = PickVertices(state, win, obj, info, toggle);
  346.           break;
  347.         case PICK_EDGE:
  348.           hits = PickEdges(state, win, obj, info, toggle);
  349.           break;
  350.         case PICK_FACE:
  351.           hits = PickFaces(state, win, obj, info, toggle);
  352.           break;
  353.         case PICK_OBJECT:
  354.           hits = PickObject(state, win, obj, info, toggle);
  355.           break;
  356.         default:
  357.           stprintf(state, "SYSTEM ERROR:  Illegal pickmode option.\n");
  358.         }
  359.       
  360.       /* If no hits on this object, set its mode to PICK_NONE. */
  361.       if (hits == 0)
  362.         OBJ_PICKMODE(obj) = PICK_NONE;
  363.       
  364.       /* Increment the count of hit elements. */
  365.       *first_id += hits;
  366.     }
  367.   else if (obj->type & OBJECT) 
  368.     {
  369.       /* Recursively examine all the objects in the group. */
  370.       hits = 0;
  371.       for (child = obj->u.grp.children; child != NULL;
  372.            child = child->sibling)
  373.         hits += PickObjRecurs(state, win, child,
  374.                               &local_info, mode, toggle, first_id);
  375.       
  376.       OBJ_HITS(obj) = hits;
  377.       if (hits == 0)
  378.         OBJ_PICKMODE(obj) = PICK_NONE;
  379.       else
  380.         OBJ_PICKMODE(obj) = PICK_BELOW;
  381.     }
  382.   else 
  383.     {
  384.       stprintf(state, "SYSTEM ERROR:  Object type not defined.\n");
  385.       popattributes();
  386.       popmatrix();
  387.       return 0;
  388.     }
  389.   
  390.   /* Restore the transformation matrix. */
  391.   popattributes();
  392.   popmatrix();
  393.   return hits;
  394. }
  395.  
  396.  
  397. /* --------------------------- CreatePickVdata ---------------------------- */
  398. char *CreatePickVdata (state_t *state, object_t *obj)
  399. {
  400.   int num;
  401.   
  402.   /* Get the data.  If it does not exist, create it. */
  403.   if (OBJ_INFO(obj) == NULL) 
  404.     {
  405.       stprintf(state, "ERROR:  Object does not have info record.\n");
  406.       return NULL;
  407.     }
  408.   
  409.   if (OBJ_PICKLIST(obj) == NULL) 
  410.     {
  411.       /* Make the vdata large enough to handle either vertices */
  412.       /* or faces. */
  413.       num = MAX(OBJ_STATS(obj, PCOORD, 0).rec_count,
  414.                 OBJ_STATS(obj, MCONNECT, 0).rec_count);
  415.       OBJ_PICKLIST(obj) = PVCALLOC(num, char);
  416.       OBJ_PICKLISTSIZE(obj) = num;
  417.     }
  418.   
  419.   return obj->info->picked;
  420. }
  421.  
  422.  
  423. /* -------------------------- ProcessSelections --------------------------- */
  424. /* ProcessSelections gets the ids of "hit" objects and sets or clears the */
  425. /* corresponding bytes in the PICKED dataset.  Returns the number of */
  426. /* objects that were hit. */
  427. long ProcessSelections (short *buffer, long count, char *picked, int toggle)
  428. {
  429.   long num, hits;
  430.   long i;
  431.   long base;
  432.   char *pickflag;
  433.  
  434.   PVD (("Entered ProcessSelections, count is %d\n", count));
  435.   
  436.   /* Close the selection buffer and find out how many hits there were. */
  437.   hits = 0;
  438.   num = endselect(buffer);
  439.   
  440.   /* Clear the next few entries in the picked buffer. */
  441.   base = 256 * ((count-1)/256);
  442.   PVD (("base is %d\n", base));
  443.   if (toggle) 
  444.     {
  445.       for (i = base; i < count; i++) 
  446.         {
  447.           PVD (("base is %d count is %d i is %d\n", base, count, i));
  448.           if (picked[i] == TRUE)
  449.             hits++;
  450.         }
  451.     }
  452.   else 
  453.     {
  454.       for (i = base; i < count; i++) 
  455.         {
  456.           PVD (("base is %d count is %d i is %d\n", base, count, i));
  457.           picked[i] = FALSE;
  458.         }
  459.     }
  460.   
  461.   /* Using count as a base in the PICKED dataset, hits in the buffer */
  462.   /* are copied to it. */
  463.   for (i = 0; i < num; i++) 
  464.     {
  465.       pickflag = &picked[base + buffer[i*2+1]];
  466.       if (toggle) 
  467.         {
  468.           if (*pickflag) 
  469.             {
  470.               hits--;
  471.               *pickflag = FALSE;
  472.             }
  473.           else 
  474.             {
  475.               hits++;
  476.               *pickflag = TRUE;
  477.             }
  478.         }
  479.       else 
  480.         {
  481.           hits++;
  482.           *pickflag = TRUE;
  483.         }
  484.     }
  485.   
  486.   return hits;
  487. }
  488.  
  489.  
  490. /* ----------------------------- PickVertices ----------------------------- */
  491. long PickVertices (state_t *state, window_t *win, object_t *obj,
  492.                    objinfo_t *info, int toggle)
  493. {
  494.   long count;
  495.   
  496.   Vdata_t **vdata;
  497.   Vdata_t *pcoord_v;
  498.   
  499.   float    (*pcoord)[DIMS];
  500.   char *picked;
  501.   
  502.   short    buffer[1024];
  503.   long hits;
  504.     
  505.   /* Get pointers to the pertinent data sets */
  506.   vdata = obj->u.obj.vdata;
  507.   if ( (pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
  508.     return 0;
  509.   
  510.   /* Get a pointer to the PICKED dataset.  Create it, if necessary. */
  511.   picked = CreatePickVdata(state, obj);
  512.   
  513.   /* Set up the consolidated coordinate array pointer. */
  514.   pcoord = (float (*)[DIMS]) pcoord_v->data;
  515.   count = 0;
  516.   assert (pcoord_v->stats[0].type == PVFLOAT);
  517.   
  518.   /* No color information.  Use foreground and draw the */
  519.   /* appropriate shapes. */
  520.   initnames();
  521.   hits = 0;
  522.   gselect(buffer, 1024);
  523.   while (count < pcoord_v->stats[0].rec_count) 
  524.     {
  525.       /* Draw the vertex. */
  526.       loadname((short) (count&255));
  527.       bgnpoint();
  528.       v3f(*pcoord);
  529.       endpoint();
  530.       
  531.       /* Move to the next x, y, z set and decrement the */
  532.       /* count. */
  533.       pcoord++;
  534.       count++;
  535.       
  536.       /* The Iris has a limit of 255 points before */
  537.       /* the buffer has to be flushed. */
  538.       if (!(count & 255)) 
  539.         {
  540.           hits += ProcessSelections(buffer, count, picked, toggle);
  541.           initnames();
  542.           gselect(buffer, 1024);
  543.         }
  544.     }
  545.   hits += ProcessSelections(buffer, count, picked, toggle);
  546.   
  547.   /* Set the object's pick mode and hits accordingly. */
  548.   OBJ_HITS(obj) = hits;
  549.   if (OBJ_HITS(obj) == 0)
  550.     OBJ_PICKMODE(obj) = PICK_NONE;
  551.   else
  552.     OBJ_PICKMODE(obj) = PICK_VERTEX;
  553.   
  554.   return hits;
  555. }
  556.  
  557.  
  558. /* ------------------------------ PickEdges ------------------------------- */
  559. long PickEdges (state_t *state, window_t *win, object_t *obj, objinfo_t *info,
  560.                 int toggle)
  561. {
  562.   long count;
  563.   
  564.   Vdata_t **vdata;
  565.   Vdata_t *pcoord_v;
  566.   Vdata_t *connect_v;
  567.   
  568.   float    (*pcoord)[DIMS];
  569.   int *connect;
  570.   char *picked;
  571.   
  572.   int i;
  573.   int nvert;
  574.   int vertex;
  575.   
  576.   short    buffer[1024];
  577.   long hits;
  578.   
  579.   /* Get pointers to the pertinent data sets */
  580.   vdata = obj->u.obj.vdata;
  581.   if ( (connect_v = get_vdata(state, vdata[CONNECT])) == NULL) 
  582.     {
  583.       if ( (connect_v = get_vdata(state, vdata[MCONNECT])) == NULL)
  584.         return PickVertices(state, win, obj, info, toggle);
  585.     }
  586.   if ( (pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
  587.     return 0;
  588.   
  589.   /* Get a pointer to the PICKED vdata.  Create it, if necessary. */
  590.   picked = CreatePickVdata(state, obj);
  591.   
  592.   /* Collect connectivity information for drawing. */
  593.   connect = (int *) connect_v->data;
  594.   count = 0;
  595.   nvert = connect_v->stats[0].rec_size;
  596.   
  597.   /* Set up the consolidated coordinate array pointer. */
  598.   pcoord = (float (*)[DIMS]) pcoord_v->data;
  599.   assert (pcoord_v->stats[0].type == PVFLOAT);
  600.   
  601.   /* No color information.  Use foreground and draw the */
  602.   /* appropriate shapes. */
  603.   initnames();
  604.   hits = 0;
  605.   gselect(buffer, 1024);
  606.   while (count < connect_v->stats[0].rec_count) 
  607.     {
  608.       loadname((short) count&255);
  609.       bgnclosedline();
  610.       for (i = nvert; i > 0; i--) 
  611.         {
  612.           if ( (vertex = *(connect++)-1) == -1) 
  613.             {
  614.               connect += i-1;
  615.               break;
  616.             }
  617.           v3f(pcoord[vertex]);
  618.         }
  619.       endclosedline();
  620.       
  621.       count++;
  622.       
  623.       /* The Iris has a limit of 255 points before */
  624.       /* the buffer has to be flushed. */
  625.       if (!(count & 255)) 
  626.         {
  627.           hits += ProcessSelections(buffer, count, picked, toggle);
  628.           initnames();
  629.           gselect(buffer, 1024);
  630.         }
  631.     }
  632.   
  633.   hits += ProcessSelections(buffer, count, picked, toggle);
  634.   
  635.   /* Set the object's pick mode and hits accordingly. */
  636.   OBJ_HITS(obj) = hits;
  637.   if (OBJ_HITS(obj) == 0)
  638.     OBJ_PICKMODE(obj) = PICK_NONE;
  639.   else
  640.     OBJ_PICKMODE(obj) = PICK_EDGE;
  641.   
  642.   return hits;
  643. }
  644.  
  645.  
  646. /* ------------------------------ PickFaces ------------------------------- */
  647. long PickFaces (state_t *state, window_t *win, object_t *obj, objinfo_t *info,
  648.                 int toggle)
  649. {
  650.   long    count;
  651.   
  652.   Vdata_t **vdata;
  653.   Vdata_t *pcoord_v;
  654.   Vdata_t *connect_v;
  655.   
  656.   float (*pcoord)[DIMS];
  657.   int *connect;
  658.   char *picked;
  659.   
  660.   int i;
  661.   int nvert;
  662.   int vertex;
  663.   
  664.   short    buffer[1024];
  665.   long hits;
  666.  
  667.   /* Get pointers to the pertinent data sets */
  668.   vdata = obj->u.obj.vdata;
  669.   if ( (connect_v = get_vdata(state, vdata[CONNECT])) == NULL)
  670.     if ( (connect_v = get_vdata(state, vdata[MCONNECT])) == NULL)
  671.       return PickVertices(state, win, obj, info, toggle);
  672.  
  673.   if ( (pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
  674.     return 0;
  675.   
  676.   /* Get a pointer to the PICKED vdata.  Create it, if necessary. */
  677.   picked = CreatePickVdata(state, obj);
  678.   
  679.   /* Collect connectivity information for drawing. */
  680.   connect = (int *) connect_v->data;
  681.   count = 0;
  682.   nvert = connect_v->stats[0].rec_size;
  683.     
  684.   /* Set up the consolidated coordinate array pointer. */
  685.   pcoord = (float (*)[DIMS]) pcoord_v->data;
  686.   assert (pcoord_v->stats[0].type == PVFLOAT);
  687.   
  688.   /* No color information.  Use foreground and draw the */
  689.   /* appropriate shapes. */
  690.   hits = 0;
  691.   initnames();
  692.   gselect(buffer, 1024);
  693.   PVD (("Starting; count is %d, connect_v->stats[0].rec_count is %d\n",
  694.         count, connect_v->stats[0].rec_count));
  695.   while (count < connect_v->stats[0].rec_count) 
  696.     {
  697.       /* PVD (("Loading name %d\n", (short) (count&255))); */
  698.       loadname((short) (count&255));
  699.       bgnpolygon();
  700.       for (i = nvert; i > 0; i--) 
  701.         {
  702.           if ( (vertex = *(connect++)-1) == -1) 
  703.             {
  704.               connect += i-1;
  705.               break;
  706.             }
  707.           
  708.           v3f(pcoord[vertex]);
  709.         }
  710.       endpolygon();
  711.       
  712.       count++;
  713.       
  714.       /* The Iris has a limit of 256 points before */
  715.       /* the buffer has to be flushed. */
  716.       if (!(count & 255)) 
  717.         {
  718.           PVD (("Satisfied !(count & 255), resetting select\n"));
  719.           PVD (("Passing ProcessSelections count=%d\n", count));
  720.           hits += ProcessSelections(buffer, count, picked, toggle);
  721.           initnames();
  722.           gselect(buffer, 1024);
  723.         }
  724.     }
  725.   hits += ProcessSelections(buffer, count, picked, toggle);
  726.   
  727.   /* Set the object's pick mode and hits accordingly. */
  728.   OBJ_HITS(obj) = hits;
  729.   if (OBJ_HITS(obj) == 0)
  730.     OBJ_PICKMODE(obj) = PICK_NONE;
  731.   else
  732.     OBJ_PICKMODE(obj) = PICK_FACE;
  733.   
  734.   return hits;
  735. }
  736.  
  737.  
  738. /* ------------------------------ PickObject ------------------------------ */
  739. long PickObject  (state_t *state, window_t *win, object_t *obj, 
  740.                   objinfo_t *info, int toggle)
  741. {
  742.   long hit;
  743.   pickmode_t prev_pickmode;
  744.  
  745.   prev_pickmode = OBJ_PICKMODE(obj);
  746.   
  747.   hit = (PickFaces(state, win, obj, info, FALSE) != 0);
  748.   
  749.   /* If the object was previously selected and the user wants to */
  750.   /* toggle objects that were hit, and the object was hit, then */
  751.   /* turn it off. */
  752.   if (toggle) 
  753.     {
  754.       if (prev_pickmode == PICK_OBJECT) 
  755.         {
  756.           if (hit)
  757.             hit = 0;
  758.           else
  759.             hit = 1;
  760.         }
  761.     }
  762.   
  763.   if (hit) 
  764.     {
  765.       OBJ_HITS(obj) = 1;
  766.       OBJ_PICKMODE(obj) = PICK_OBJECT;
  767.     }
  768.   else 
  769.     {
  770.       OBJ_HITS(obj) = 0;
  771.       OBJ_PICKMODE(obj) = PICK_NONE;
  772.     }
  773.   
  774.   return OBJ_HITS(obj);
  775. }
  776.